package com.mzj.saas.redis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.mzj.saas.commons.Constant;
import com.mzj.saas.commons.DateUtils;
import com.mzj.saas.commons.enums.UserLoginTypeEnum;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.mservice.auth.vo.RealPeopleCertificationVO;
import com.mzj.saas.mservice.backlog.vo.BacklogItemRedisVo;
import com.mzj.saas.mservice.bill.vo.PaymentBillRedisVo;
import com.mzj.saas.mservice.property.vo.RepairsPaymentRedisVo;
import com.mzj.saas.mservice.smartlock.vo.SmartLockFingerprintVO;
import com.mzj.saas.mservice.smartlock.vo.SmartLockVO;
import com.mzj.saas.mservice.sys.entity.Permission;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {
    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    @Autowired
    @Qualifier("stringRedisTemplate9")
    private StringRedisTemplate redisTemplate9;

    /**
     * 获取系统参数数据
     *
     * @param key
     * @return
     */
    public String getValue(String key) {
        Object object = redisTemplate.opsForHash().get(Constant.MZJ_MG_PARAMS, key);
        if (object == null) {
            return null;
        }

        return object.toString().replace("\"", "");
    }

    /**
     * 查询用户TOKEN缓存信息
     * 鉴权
     *
     * @param token
     * @return
     * @author shun
     * @date 2021年1月26日
     */
    public TokenRedisVo findTokenVo(String token) {
        Object object = redisTemplate.opsForValue().get(token);
        if (object != null) {
            TokenRedisVo vo = JSON.parseObject(object.toString(), TokenRedisVo.class);

            // 统一处理用户角色类型：1企业用户、2普通用户
            if (vo.getLoginType() != null && vo.getLoginType() == UserLoginTypeEnum.ENTERPRISE.getValue()) {
                /**
                 * 系统中所有取用户id的地方，都是取id，所以如果是企业用户，设置id为企业用户的id进行返回
                 */
                vo.setId(vo.getEnterpriseUserId());
            }
            return vo;
        }

        return null;
    }

    /**
     * 删除缓存token
     *
     * @param
     * @author shun
     * @date 2021年3月19日
     */
    public void deleteLoginToken(String token) {
        redisTemplate.delete(token);
    }

    /**
     * 查询用户TOKEN缓存信息
     *
     * @param token
     * @return
     * @author shun
     * @date 2021年1月26日
     */
    public TokenRedisVo swichUserTokenVo(String token) {
        Object object = redisTemplate.opsForValue().get(token);
        if (object != null) {
            TokenRedisVo vo = JSON.parseObject(object.toString(), TokenRedisVo.class);
            return vo;
        }
        return null;
    }

    /**
     * 缓存短信验证码
     *
     * @param mobile
     * @param code
     * @author shun
     * @date 2021年3月19日
     */
    public void putSmsCode(String mobile, String code) {
        redisTemplate.opsForValue().set(code, mobile, 300, TimeUnit.SECONDS);
    }

    /**
     * 删除短信验证码
     *
     * @param code
     * @author shun
     * @date 2021年3月19日
     */
    public void deleteSmsCode(String code) {
        redisTemplate.delete(code);
    }

    /**
     * 获取验证码手机号
     *
     * @param code
     * @return
     * @author shun
     * @date 2021年3月19日
     */
    public String getSmsCodeMobile(String code) {
        return redisTemplate.opsForValue().get(code);
    }

    /**
     * 获取所有权限列表
     *
     * @return
     * @author shun
     * @date 2021年6月4日
     */
    public List<Permission> getAllPerissionRedis() {
        String permision = redisTemplate.opsForValue().get(Constant.ALL_PERMISSION);
        if (StringUtils.isBlank(permision)) {
            return null;
        }

        return JSONArray.parseArray(permision, Permission.class);
    }

    /**
     * 缓存权限
     *
     * @param list
     * @author shun
     * @date 2021年6月4日
     */
    public void putAllPerissionRedis(List<Permission> list) {
        redisTemplate.opsForValue().set(Constant.ALL_PERMISSION, JSONObject.toJSONString(list), 60, TimeUnit.MINUTES);
    }

    /**
     * 缓存智能锁 回调入参callBackId
     *
     * @param
     * @param vo
     */
    public void putLockCallBack(String key, SmartLockVO vo) {
        redisTemplate.opsForValue().set(Constant.LOCK_CALLBACK + ":" + key, JSONObject.toJSONString(vo), 5,
                TimeUnit.DAYS);
    }

    /**
     * 获取智能锁 回调
     *
     * @param
     * @return
     */
    public SmartLockVO getLockCallBack(String key) {
        Object object = redisTemplate.opsForValue().get(Constant.LOCK_CALLBACK + ":" + key);

        if (object == null) {
            return null;
        }
        return JSONObject.parseObject(object.toString(), SmartLockVO.class);
    }

    /**
     * 删除智能锁 回调
     *
     * @param
     */
    public void delLockClassBack(String key, SmartLockVO vo) {
        redisTemplate.opsForValue().set(Constant.LOCK_CALLBACK + ":" + key, JSONObject.toJSONString(vo), 30,
                TimeUnit.MINUTES);
    }

    /**
     * 获取已重复发送次数
     *
     * @return
     */
    public Integer getRepeatLock(String type, String sn) {

        String num = redisTemplate.opsForValue().get("repeatLock:" + type + ":" + sn);

        if (StringUtils.isBlank(num)) {
            redisTemplate.opsForValue().set("repeatLock:" + type + ":" + sn, "1", DateUtils.getTimeMillis(),
                    TimeUnit.SECONDS);
            return 1;
        }
        return Integer.parseInt(num);
    }

    /**
     * 重复发送自增
     *
     * @param type
     * @param sn
     */
    public void putRepeatLock(String type, String sn) {
        redisTemplate.opsForValue().increment("repeatLock:" + type + ":" + sn, 1);
    }

    /**
     * 缓存预支付账单(租金/押金, 其它物业生活缴费)
     */
    public void putPaymentBill(PaymentBillRedisVo vo) {
        redisTemplate.opsForValue().set(Constant.APP_PAY_ORDER + ":" + vo.getOutTradeNo(), JSONObject.toJSONString(vo),
                15, TimeUnit.MINUTES);
    }

    /**
     * 缓存预支付账单(维修费用)
     */
    public void putPaymentRepairs(RepairsPaymentRedisVo vo) {
        redisTemplate.opsForValue().set(Constant.APP_PAY_ORDER + ":" + vo.getOutTradeNo(), JSONObject.toJSONString(vo),
                15, TimeUnit.MINUTES);
    }

    /**
     * 缓存预支付账单(待办事项)
     */
    public void putPaymentBacklog(BacklogItemRedisVo vo) {
        redisTemplate.opsForValue().set(Constant.APP_PAY_ORDER + ":" + vo.getOutTradeNo(), JSONObject.toJSONString(vo),
                15, TimeUnit.MINUTES);
    }

    /**
     * 获取预支付订单
     *
     * @param outradeNo
     * @param clazz
     * @return
     */
    public <T> T getPaymentOrder(String outradeNo, Class<T> clazz) {

        Object object = redisTemplate.opsForValue().get(Constant.APP_PAY_ORDER + ":" + outradeNo);

        if (object == null) {
            return null;
        }
        return JSONObject.parseObject(object.toString(), clazz);
    }

    /**
     * 缓存企业业务分类id
     *
     * @param orgid      企业id
     * @param categoryId 业务分类id
     * @author shun
     * @date 2021年6月9日
     */
    public void putCategoryId(Long orgid, Long categoryId) {
        redisTemplate.opsForHash().put(Constant.CATEGORY_PARAM, orgid + "", categoryId + "");
    }

    /**
     * 获取企业业务分类id
     *
     * @param orgid
     * @return
     * @author shun
     * @date 2021年6月9日
     */
    public Long getCategoryId(Long orgid) {
        Object object = redisTemplate.opsForHash().get(Constant.CATEGORY_PARAM, orgid + "");
        if (object == null) {
            return null;
        }

        return Long.parseLong(object.toString());
    }

    /**
     * 获取企业印章
     *
     * @param orgid
     * @return
     * @author shun
     * @date 2021年6月9日
     */
    public Long getOrgSealId(Long orgid) {
        Object object = redisTemplate.opsForHash().get(Constant.SEAL_PARAM, orgid + "");
        if (object == null) {
            return null;
        }

        return Long.parseLong(object.toString());
    }

    /**
     * 缓存企业印章ID
     *
     * @param orgid  企业id
     * @param sealId 签章id
     * @author shun
     * @date 2021年6月9日
     */
    public void putOrgSealId(Long orgid, Long sealId) {
        redisTemplate.opsForHash().put(Constant.SEAL_PARAM, orgid + "", sealId + "");
    }

    /**
     * 带过期时间的自增
     *
     * @param key
     * @param liveTime
     * @return
     * @author shun
     * @date 2021年6月24日
     */
    public Long incr(String key, long liveTime) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();

        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.HOURS);
        }
        return increment;
    }

    /**
     * 缓存智能锁指纹数据
     *
     * @param
     * @param vo
     */
    public void putLockFingerprintCallBack(String key, SmartLockFingerprintVO vo) {
        redisTemplate.opsForValue().set(Constant.LOCK_CALLBACK + ":" + key, JSONObject.toJSONString(vo), 1,
                TimeUnit.DAYS);
    }

    /**
     * 获取智能锁缓存指纹数据
     *
     * @param
     * @return
     */
    public SmartLockFingerprintVO getLockFingerprintCallBack(String key) {
        Object object = redisTemplate.opsForValue().get(Constant.LOCK_CALLBACK + ":" + key);

        if (object == null) {
            return null;
        }
        return JSONObject.parseObject(object.toString(), SmartLockFingerprintVO.class);
    }


    /**
     * 缓存亚洛略特token
     *
     * @param token
     * @author shun
     * @date 2021年7月26日
     */
    public void putYltToken(String token) {
        redisTemplate.opsForValue().set(Constant.LOCK_YLT_TOKEN_TIME, token, 145, TimeUnit.MINUTES);
    }

    /**
     * 缓存亚洛略token
     *
     * @param
     * @author shun
     * @date 2021年7月26日
     */
    public String getYltToken() {
        return (String) redisTemplate.opsForValue().get(Constant.LOCK_YLT_TOKEN_TIME);
    }

    /**
     * 缓存-蓝牙授权密码
     *
     * @param
     * @author shun
     * @date 2021年7月26日
     */
    public void putYltFBLEPassword(String authorizationID, String pwd) {
        redisTemplate.opsForValue().set(Constant.LOCK_YLT_FBLE_PWD + "." + authorizationID, pwd, 30, TimeUnit.MINUTES);
    }

    /**
     * 获取蓝牙授权密码
     *
     * @param
     * @author shun
     * @date 2021年7月26日
     */
    public String getYltFBLEPassword(String authorizationID) {
        return (String) redisTemplate.opsForValue().get(Constant.LOCK_YLT_FBLE_PWD + "." + authorizationID);
    }


    /**
     * 缓存账单催缴记录
     *
     * @param billId
     * @author shun
     * @date 2022年7月4日
     */
    public void putBillId(String billId) {
        redisTemplate.opsForValue().set(Constant.BILL_WORTH_HOUR + ":" + billId, billId, 1, TimeUnit.DAYS);
    }

    /**
     * 获取账单催缴记录
     *
     * @param billId
     * @author shun
     * @date 2022年7月4日
     */
    public String gutBillId(String billId) {
        return (String) redisTemplate.opsForValue().get(Constant.BILL_WORTH_HOUR + ":" + billId);
    }


    /**
     * 缓存 实人认证身份记录
     *
     * @param certifyId
     * @param vo
     */
    public void putCertifyId(String certifyId, RealPeopleCertificationVO vo) {
        redisTemplate.opsForValue().set(Constant.CERTIFY_ID + ":" + certifyId, JSON.toJSONString(vo), 31, TimeUnit.MINUTES);

    }

    /**
     * 获取 实人认证身份记录
     *
     * @param certifyId
     */
    public RealPeopleCertificationVO getCertifyId(String certifyId) {
        Object object = redisTemplate.opsForValue().get(Constant.CERTIFY_ID + ":" + certifyId);
        if (object != null) {
            RealPeopleCertificationVO vo = JSON.parseObject(object.toString(), RealPeopleCertificationVO.class);
            return vo;
        }
        return null;
    }

    /**
     * 缓存锁心跳状态
     *
     * @param
     * @param minutesTime
     * @author shun
     * @date 2022年7月22日
     */
    public void putLockheartbeatStatusRedis(String mac, Integer minutesTime) {
        redisTemplate.opsForValue().set(Constant.LOCK_HEARTBEAT_STATUS + ":" + mac, "1", minutesTime, TimeUnit.MINUTES);
    }

    /**
     * 获取锁心跳状态
     *
     * @param mac
     * @return
     * @author shun
     * @date 2022年7月22日
     */
    public String getLockheartbeatStatusRedis(String mac) {
        return (String) redisTemplate.opsForValue().get(Constant.LOCK_HEARTBEAT_STATUS + ":" + mac);
    }

    /**
     * 缓存智能锁临时密码
     *
     * @param mobile
     * @param smartLockPwd
     * @author qixi
     * @date 2022年12月2日
     */
    public void putAuthTemporaryPwd(String mobile, String smartLockPwd, String houseId, Integer minutesTime) {
        redisTemplate.opsForValue().set(Constant.SMART_LOCK_PWD + ":" + mobile + ":" + houseId, smartLockPwd, minutesTime, TimeUnit.DAYS);
    }

    /**
     * 缓存智能锁临时密码
     *
     * @param mobile
     * @param smartLockPwd
     * @author qixi
     * @date 2022年12月2日
     */
    public void putAuthTemporaryPwdMinute(String mobile, String smartLockPwd, String houseId, Integer minutesTime) {
        redisTemplate.opsForValue().set(Constant.SMART_LOCK_PWD + ":" + mobile + ":" + houseId, smartLockPwd, minutesTime, TimeUnit.MINUTES);
    }

    /**
     * 删除智能锁临时密码
     *
     * @param mobile
     * @param smartLockPwd
     * @author qixi
     * @date 2022年12月2日
     */
    public void deleteAuthTemporaryPwd(String mobile, String smartLockPwd, String houseId) {
        redisTemplate.delete(Constant.SMART_LOCK_PWD + ":" + mobile + ":" + houseId);
    }

    /**
     * 获取智能锁临时密码
     *
     * @param mobile
     * @author qixi
     * @date 2022年12月2日
     */
    public String getAuthTemporaryPwd(String mobile, String houseId) {
        return (String) redisTemplate.opsForValue().get(Constant.SMART_LOCK_PWD + ":" + mobile + ":" + houseId);
    }

    /**
     * 删除智能锁临时密码
     *
     * @param mobile
     * @author qixi
     * @date 2022年12月23日
     */
    public void deleteAuthTemporaryPwd(String mobile, String houseId) {
        redisTemplate.delete(Constant.SMART_LOCK_PWD + ":" + mobile + ":" + houseId);
    }

    /**
     * 获取系统用户id
     *
     * @return
     */
    public String getSystemUser() {
        Object object = redisTemplate.opsForHash().get(Constant.MZJ_MG_PARAMS, Constant.SYSTEM_USER_NAME);
        if (object == null) {
            return null;
        }
        return object.toString();
    }

    /**
     * 获取PasS平台token
     *
     * @return
     */
    public String getToken() {
        String paaSToken = redisTemplate.opsForValue().get("paaSToken");
        if (StringUtils.isEmpty(paaSToken)) {
            try {
                HttpPost httpPost = new HttpPost("https://paas.locksuiyi.com/deviceManagement/api/login.do");
                CloseableHttpClient httpClient = HttpClients.createDefault();
                BasicResponseHandler handler = new BasicResponseHandler();
                Map<String, String> params = Maps.newHashMap();
                params.put("appKey", "c12906e319edc1ccf8f3a2e6fbeb9b35");
                params.put("secret", "118e6b21159aa518f0afe5b5f7e7a47c");
                //设置请求格式
                StringEntity entity = new StringEntity(JSON.toJSONString(params), "utf-8");//解决中文乱码问题
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
                //执行POST请求
                String execute = httpClient.execute(httpPost, handler);
                JSONObject resultJson = JSON.parseObject(execute);
                Object data = resultJson.get("data");
                JSONObject jsonObject = JSON.parseObject(data.toString());
                Object token = jsonObject.get("token");
                redisTemplate.opsForValue().set("paaSToken", token.toString(), 30, TimeUnit.MINUTES); //30分钟
                return token.toString();
            } catch (Exception e) {
                return "获取失败";
            }
        }
        return paaSToken;
    }

}
